package jp.sourceforge.akjrcp.dropsomething2;

import com.akjava.lib.rcp.undo.RcpUndoUtils;
import com.akjava.lib.swt.log.ExecuteLog;
import com.akjava.lib.swt.undo.operation.TextAndSelectUndoOperation;
import com.akjava.lib.swt.undo.operation.TextAndSelectUndoSupport;

import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.PlatformUI;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import jp.sourceforge.akjrcp.akj_betas.Akj_betasPlugin;
import jp.sourceforge.akjrcp.akj_betas.Messages;
import jp.sourceforge.akjrcp.commons.ui.widget.WidgetBuilder;
import jp.sourceforge.akjrcp.commons.util.FileNameUtils;
import jp.sourceforge.akjrcp.dropsomething.DropsomethingAction;
import jp.sourceforge.akjrcp.dropsomething.FFMpegDropSomethingTab;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegExecuter;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegOptions;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegPreference;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegUI;
import jp.sourceforge.akjrcp.ffmpeg.FFMpegUtils;
import jp.sourceforge.akjrcp.ui.FileOverwriteControler;
import jp.sourceforge.akjrcp.ui.GenericParameters;
import jp.sourceforge.akjrcp.ui.GenericParametersEditorDialog;
import jp.sourceforge.akjrcp.ui.GenericParametersEventListener;
import jp.sourceforge.akjrcp.ui.GenericParametersFFMpegPreference;
import jp.sourceforge.akjrcp.ui.GenericParametersFieldEditor;
import jp.sourceforge.akjrcp.ui.GenericParametersSaveDialog;
import jp.sourceforge.akjrcp.ui.GenericParametersTableViewer;
import jp.sourceforge.akjrcp.ui.param.ParamBoolean;

public abstract class AbstractFFMpegDropSomething2 extends DirectoryBasedDropSomething2 implements FFMpegDropSomethingTab2,TextAndSelectUndoSupport{

	
	
	protected FileOverwriteControler fileOverwriteControler;//this need she
	public static final String AVISYNTH="avisynth";

	protected FFMpegPreference preference;
	protected GenericParametersTableViewer tableViewer;


	protected AbstractDropFileGenericParametersOptionEditor editor;

	protected Button saveSetting;
	protected Button newSetting;
	
	protected FFMpegExecuter ffmpegExecuter;


	private String[] supportedFiles={"avi","mkv","mpeg","mpg","ts","rmvb","mp4"};
	private int lastSelection;

	public AbstractFFMpegDropSomething2(Composite parent, int style,String key) {
		super(parent, style,key);
	}

	public class SelectChanged implements ISelectionChangedListener{

		public void selectionChanged(SelectionChangedEvent event) {
			tableSelectionChanged();
		}
		
	}
	
	

	//TODO move upper level
	public void createPopupMenu(final GenericParametersTableViewer viewer){
		Menu menu=viewer.getPopUpMenu();
		
		MenuItem moveTop=WidgetBuilder.createPushMenu(menu, jp.sourceforge.akjrcp.ui.Messages.getString("genericparameters.top"));
		moveTop.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				doTop();
			}
		});
		MenuItem moveUp=WidgetBuilder.createPushMenu(menu, jp.sourceforge.akjrcp.ui.Messages.getString("genericparameters.up"));
		moveUp.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				doUp();
			}
		});
		MenuItem moveDown=WidgetBuilder.createPushMenu(menu, jp.sourceforge.akjrcp.ui.Messages.getString("genericparameters.down"));
		moveDown.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				doDown();
			}
		});
		MenuItem moveBottom=WidgetBuilder.createPushMenu(menu, jp.sourceforge.akjrcp.ui.Messages.getString("genericparameters.bottom"));
		moveBottom.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				doBottom();
			}
		});
		Menu clipboard=WidgetBuilder.createCascadeMenu(menu, jp.sourceforge.akjrcp.ui.Messages.getString("genericparameters.clipboard"));
		MenuItem copyBottom=WidgetBuilder.createPushMenu(clipboard, jp.sourceforge.akjrcp.ui.Messages.getString("genericparameters.copy"));
		copyBottom.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				doCopy();
			}
		});
		MenuItem pasteBottom=WidgetBuilder.createPushMenu(clipboard, jp.sourceforge.akjrcp.ui.Messages.getString("genericparameters.paste"));
		pasteBottom.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				doPaste();
			}
		});
		WidgetBuilder.createSeparateMenu(menu);
		MenuItem delete=new MenuItem(menu,SWT.PUSH);
		delete.setText(jp.sourceforge.akjrcp.ui.Messages.getString("delete"));
		delete.addSelectionListener(new SelectionListener(){

			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				
			}

			@Override
			public void widgetSelected(SelectionEvent e) {
				int index=viewer.getTable().getSelectionIndex();
				if(index>=0){//selected
				//TODO confirm dialog	
				String beforeText=toSettingText();
				GenericParameters setting=(GenericParameters) viewer.getGenericParameters().get(index);
				viewer.getGenericParameters().remove(setting);
				viewer.refresh();
				log.info("deleted:"+index);
				
				String newText=toSettingText();
				saveValue(newText,index);
				
				TextAndSelectUndoOperation operation=new TextAndSelectUndoOperation("edit",AbstractFFMpegDropSomething2.this,beforeText,index,newText,0);
				
				execOperation(operation);
				}
			}});
		
	}
	
	public void viewPartChanged(){
		RcpUndoUtils.initializeUndoContext(getViewPart().getSite(), 99);
	}
	
protected void initializeExecutes(){
		//initialize any batch
		fileOverwriteControler=null;
	}
	
//keep for future
	protected void releaseExecutes(){
	
	}
	//TODO upper or interface
	public void tableSelectionChanged(){
		GenericParameters parameters;
		saveSetting.setEnabled(false);//changed
		int selection=tableViewer.getTable().getSelectionIndex();
		if(selection>=0){
		log.info("table item changed:"+selection);
		parameters=(GenericParameters) tableViewer.getTable().getItem(tableViewer.getTable().getSelectionIndex()).getData();
		//log.info("size:"+paramList.size());
		}else{
			//setDefault
			parameters=makeDefaultGenericParameters();
		}
		
		Map map=parameters.getParameters();
		
		editor.setParameters(map);
		saveSetting.setEnabled(false);//changed
	}
	
	public abstract GenericParameters makeDefaultGenericParameters(); 


	public class GenericNew implements SelectionListener {

		public void widgetDefaultSelected(SelectionEvent e) {
			
		}

		public void widgetSelected(SelectionEvent e) {
			GenericParametersEditorDialog dialog=new GenericParametersEditorDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
			
			int result=dialog.open();
			if(result==Dialog.OK){
				String beforeText=toSettingText();
				int beforeIndex=tableViewer.getTable().getSelectionIndex();
				if(beforeIndex==-1){
					beforeIndex=0;
				}
				
				GenericParameters newed=makeDefaultGenericParameters();
				newed.setName(dialog.getName());
				newed.setComment(dialog.getComment());
				
				//setDefault parameter
				tableViewer.getGenericParameters().add(newed);
				tableViewer.refresh();
				
				//save
				GenericParameters infos[] = (GenericParameters[]) tableViewer.getGenericParameters().toArray(new GenericParameters[0]);
				String newValue=GenericParametersFieldEditor.toStoreString(infos);
				getPreferenceStore().setValue(getPreferenceKey()+"."+FFMpegDropSomethingTab2.SETTINGS,newValue);
				
				tableViewer.getTable().setSelection(tableViewer.getTable().getItemCount()-1);//select last one.
				tableSelectionChanged();//update items
				
				TextAndSelectUndoOperation operation=new TextAndSelectUndoOperation("edit",AbstractFFMpegDropSomething2.this,beforeText,beforeIndex,newValue,tableViewer.getTable().getItemCount()-1);
				execOperation(operation);
			}else{
				log.info(result);
			}
		}
	}
	
	public void execOperation(IUndoableOperation operation){
		RcpUndoUtils.execOperation(getViewPart().getSite(),operation);
		updateUndoRedoControls();
	}
	
	public abstract AbstractDropFileGenericParametersOptionEditor makeGenericParameterOptionEditor(String preferenceKey,IPreferenceStore preference);
	
	

	public class GenericEdit implements SelectionListener {
		int dialogWidth=480;
		int dialogHeight=480;
		public void widgetDefaultSelected(SelectionEvent e) {
			
		}

		public void widgetSelected(SelectionEvent e) {
			log.warn("edit called:");
			int index=tableViewer.getTable().getSelectionIndex();
			if(index==-1){
				return;
			}
			String beforeText=toSettingText();
			GenericParameters setting=(GenericParameters) tableViewer.getGenericParameters().get(index);
			
			log.trace(setting.mapToCsv(editor.getParameters()));

			GenericParametersEditorDialog dialog=new GenericParametersEditorDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
			dialog.setName(setting.getName());
			dialog.setComment(setting.getComment());
			Map newMap=editor.getParameters();
			dialog.setParameters(newMap);

			
		
		
			dialog.setDialogWidth(dialogWidth);
			dialog.setDialogHeight(dialogHeight);
			int result=dialog.open();
			
			if(result==Dialog.OK){
				lastSelection=index;
				//tableViewer.refresh();
				
				//use same
				log.warn("maybe dont work");
				//GenericParameters edited=GenericParameters.csvToParameters(dialog.getCommand());
				//setting.setParameters(edited.getParameters());
	
				//must parameter first,otherwise name and comment 'll removed
				filterSaveParameters(newMap);
				setting.setParameters(newMap);
				
				setting.setName(dialog.getName());
				setting.setComment(dialog.getComment());
				
			
				log.warn("saveValue:");
				//save
				String newText=toSettingText();
				saveValue(newText,index);
			
				TextAndSelectUndoOperation operation=new TextAndSelectUndoOperation("edit",AbstractFFMpegDropSomething2.this,beforeText,index,newText,index);
				execOperation(operation);
				//tableViewer.getTable().setSelection(index);
				//tableSelectionChanged();
			}else{
				log.info(result);
			}
			
		}
	}
	public void doRedo(){
		RcpUndoUtils.doRedo(getViewPart().getSite());
		updateUndoRedoControls();
	}
	
	public void doUndo(){
		RcpUndoUtils.doUndo(getViewPart().getSite());
		updateUndoRedoControls();
	}
	
	protected String toSettingText(){
		GenericParameters infos[] = (GenericParameters[]) tableViewer.getGenericParameters().toArray(new GenericParameters[0]);
		return GenericParametersFieldEditor.toStoreString(infos);
	}

	public IAction createUndoAction(){
		Action tmp=new Action(){
			public void run(){
				doUndo();
			}
		};
		tmp.setAccelerator(SWT.CTRL|'z');
		return tmp;
	}
	
	public IAction createRedoAction(){
		Action tmp=new Action(){
			public void run(){
				doRedo();
			}
		};
		tmp.setAccelerator(SWT.CTRL|'y');
		return tmp;
	}
	
	/*
	 * for undo operation
	 */
	public void saveValue(String value,int index){
		lastSelection=index;
		getPreferenceStore().setValue(getPreferenceKey()+"."+SETTINGS,value);
		//after set automatic reload
	}
	
	public void setUndoRedoValue(String value,int index){
		saveValue(value,index);
	}
	

	public void doTop(){
		int beforeIndex=tableViewer.getCurrentSelectionIndex();
		if(beforeIndex==-1){
			return;
		}
		String beforeText=toSettingText();
		
		tableViewer.moveTop(beforeIndex);
		
		int afterIndex=0;
		String afterText=toSettingText();
		TextAndSelectUndoOperation operation=new TextAndSelectUndoOperation("edit",AbstractFFMpegDropSomething2.this,beforeText,beforeIndex,afterText,afterIndex);
		execOperation(operation);
	}
	public void doCopy(){
		int beforeIndex=tableViewer.getCurrentSelectionIndex();
		if(beforeIndex==-1){
			return;
		}

		tableViewer.copyClipboard(beforeIndex);
		

	}
	public void doPaste(){
		int beforeIndex=tableViewer.getCurrentSelectionIndex();
		if(beforeIndex==-1){
			return;
		}
		String beforeText=toSettingText();
		
		tableViewer.pasteClipBoard();
		
		int afterIndex=beforeIndex;
		String afterText=toSettingText();
		TextAndSelectUndoOperation operation=new TextAndSelectUndoOperation("edit",AbstractFFMpegDropSomething2.this,beforeText,beforeIndex,afterText,afterIndex);
		execOperation(operation);
	}
	public void doDown(){
		int beforeIndex=tableViewer.getCurrentSelectionIndex();
		if(beforeIndex==-1){
			return;
		}
		String beforeText=toSettingText();
		
		tableViewer.moveDown(beforeIndex);
		
		int afterIndex=0;
		String afterText=toSettingText();
		TextAndSelectUndoOperation operation=new TextAndSelectUndoOperation("edit",AbstractFFMpegDropSomething2.this,beforeText,beforeIndex,afterText,afterIndex);
		execOperation(operation);
	}
	public void doUp(){
		int beforeIndex=tableViewer.getCurrentSelectionIndex();
		if(beforeIndex==-1){
			return;
		}
		String beforeText=toSettingText();
		
		tableViewer.moveUp(beforeIndex);
		
		int afterIndex=0;
		String afterText=toSettingText();
		TextAndSelectUndoOperation operation=new TextAndSelectUndoOperation("edit",AbstractFFMpegDropSomething2.this,beforeText,beforeIndex,afterText,afterIndex);
		execOperation(operation);
	}
	
	public void doBottom(){
		int beforeIndex=tableViewer.getCurrentSelectionIndex();
		if(beforeIndex==-1){
			return;
		}
		String beforeText=toSettingText();
		
		tableViewer.moveBottom(beforeIndex);
		
		int afterIndex=0;
		String afterText=toSettingText();
		TextAndSelectUndoOperation operation=new TextAndSelectUndoOperation("edit",AbstractFFMpegDropSomething2.this,beforeText,beforeIndex,afterText,afterIndex);
		execOperation(operation);
	}
	
	public class GenericSave implements SelectionListener {

		public void widgetDefaultSelected(SelectionEvent e) {
			
		}

		public void widgetSelected(SelectionEvent e) {
		GenericParameters parameter=tableViewer.getCurrentSelection();
		GenericParametersSaveDialog dialog=new GenericParametersSaveDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
		String oldName=parameter.getName();
		if(parameter==null){
		dialog.setName(Messages.getString("dropsomething.newsetting"));	
		}else{
		String newName=tableViewer.copiedName(parameter);
		dialog.setName(newName);
		dialog.setComment(parameter.getComment());
		}
		
		String beforeText=toSettingText();
		int beforeIndex=tableViewer.getTable().getSelectionIndex();
		if(beforeIndex==-1){
			beforeIndex=0;
		}
		
		int ret=dialog.open();
		int selection;
		if(ret==Dialog.OK){
			log.info("Save:"+dialog.isSaveOverwrite());
			Map<String ,String> newMap=editor.getParameters();
			filterSaveParameters(newMap);
			if(dialog.isSaveOverwrite()){
//				overwrite or copy
				parameter.setParameters(newMap);
				parameter.setName(oldName);//re set old name.
				parameter.setComment(dialog.getComment());
				selection=tableViewer.getTable().getSelectionIndex();
			}else{
				GenericParameters newParam=new GenericParameters(newMap);
				newParam.setName(dialog.getName());
				newParam.setComment(dialog.getComment());
				
				tableViewer.getGenericParameters().add(newParam);
				tableViewer.refresh();//
				selection=tableViewer.getTable().getItemCount()-1;//added item.
			}
			//store data
			
			GenericParameters infos[] = (GenericParameters[]) tableViewer.getGenericParameters().toArray(new GenericParameters[0]);
			//String oldValue=getPreferenceStore().getString(H264SettingPage.EXPORT_H264_SETTINGS);
			String newValue=GenericParametersFieldEditor.toStoreString(infos);
			//set only difference
			
//			save store
			log.info("saved:"+getPreferenceKey()+"."+FFMpegDropSomethingTab2.SETTINGS);
			getPreferenceStore().setValue(getPreferenceKey()+"."+FFMpegDropSomethingTab2.SETTINGS,newValue);
			
			
			tableViewer.getTable().setSelection(selection);
			tableSelectionChanged();
			//update value;
			
			TextAndSelectUndoOperation operation=new TextAndSelectUndoOperation("edit",AbstractFFMpegDropSomething2.this,beforeText,beforeIndex,newValue,selection);
			execOperation(operation);
		}
		}

	}
	//default nothing do
	protected void filterSaveParameters(Map<String ,String> map){
		
	}
	
	public class StoreSelect implements ISelectionChangedListener{

		public void selectionChanged(SelectionChangedEvent event) {
			log.info("saved:"+getPreferenceKey()+"."+SELECTION_INDEX);
			getPreferenceStore().setValue(getPreferenceKey()+"."+SELECTION_INDEX, tableViewer.getTable().getSelectionIndex());
		}
		
	}
	

	

	

	
	public void selectCombo(CCombo combo,String value){
		int s=combo.getItemCount();
		for (int i = 0; i <s; i++) {
			if(combo.getItem(i).equals(value)){
				combo.select(i);
				break;
			}
		}
	}
	


	

	
	
	public String toTime(long bps,long maxMega){
		long bytes=bps/8;
		
		long second=maxMega*1024*1024/bytes;
		long hour=second/3600;
		second=second%3600;
		long min=second/60;
		long sec=second%60;
		
		String hstring=""+hour;
		if(hstring.length()<2){
			hstring="0"+hstring;
		}
		
		String mstring=""+min;
		if(mstring.length()<2){
			mstring="0"+mstring;
		}
		
		String sstring=""+sec;
		if(sstring.length()<2){
			sstring="0"+sstring;
		}
		return hstring+":"+mstring+":"+sstring;
	}

	
	public void updateUndoRedoControls(){

			Control[] undos=undoControls.toArray(new Control[undoControls.size()]);

			Control[] redos=redoControls.toArray(new Control[redoControls.size()]);

			RcpUndoUtils.updateUndoRedoControls(getViewPart().getSite(), undos, redos);
	}
	
	public void updateSettingTable(){
		List list=GenericParametersTableViewer.loadList(Akj_betasPlugin.getDefault().getPreferenceStore().getString(getPreferenceKey()+"."+FFMpegDropSomethingTab.SETTINGS));
		

		tableViewer.setGenericParametersList(list);
		
		//select if have list.
		if(tableViewer.getTable().getItemCount()>0){
			
			//now lastselection setted only edit for 
			if(lastSelection>=0 && lastSelection<tableViewer.getTable().getItemCount()){
			tableViewer.getTable().setSelection(lastSelection);	
			}else{//invalid last selection
			tableViewer.getTable().setSelection(0);
			}
			tableSelectionChanged();
			}
		
		
	}
	public class PreferenceStoreMonitor implements IPropertyChangeListener {

		public void propertyChange(PropertyChangeEvent event) {
			log.info(event.getProperty());
			if (event.getProperty().equals(getPreferenceKey()+"."+FFMpegDropSomethingTab.SETTINGS)) {
				updateSettingTable();
			}
		}
	}
	
	public void afterConvert() {
		// TODO Auto-generated method stub
		
	}
	
	//overwrite only work when ffmpeg is available
	public boolean isCanConvert(){
		
		String ffmpegPath = FFMpegUI.getFFmpegOrPureFFMpeg();

		if (!FFMpegUI.isFFMpegOrPureFFMpegAvailable(ffmpegPath)) {
			setCantConvertStatusbarMessage(Messages.getString("ffmpeg_statusbar.no_ffmpeg"));
		return false;
		}
		
		//check export setting.
		
		return super.isCanConvert();
	}

	public void cancelExecute() {
		ffmpegExecuter.cancel();
		File f=ffmpegExecuter.getCurrentOutputFile();
		long wait=100;
		int trycount=10;
		boolean ret=false;;
		for(int i=0;i<trycount;i++){
		if(f!=null && f.exists()){
			try {
				Thread.sleep(wait);
			} catch (InterruptedException e) {
				// TODO �����������ꂽ catch �u���b�N
				e.printStackTrace();
			}
			ret=f.delete();
			if(ret==true){
				break;
			}
		}
			log.info("deleted:"+ret+","+f.getAbsolutePath());
		}
	}

	public void updateStatus() {
		
		boolean sameFolder=false;
		String exportDir=null;
		if(editor.getItem(DropFileGenericParameterSetting.SAME_DIRECTORY)!=null){
		if(((ParamBoolean)editor.getItem(DropFileGenericParameterSetting.SAME_DIRECTORY)).getBoolean()){//true;
			sameFolder=true;
		}
		}else{
			log.warn("same directory not found");
		}
		
		if(editor.getItem(DropFileGenericParameterSetting.EXPORT_DIR)!=null){
		if(!editor.getItem(DropFileGenericParameterSetting.EXPORT_DIR).getValue().equals("")){//valid;
			exportDir=editor.getItem(DropFileGenericParameterSetting.EXPORT_DIR).getValue();
		}
		}else{
			log.warn("export dir not found");
		}
		if(sameFolder || exportDir!=null){
			setMessage(Messages.getString("dropsomething.drag_folder"));
			setCanConvert(true);
		}else{
			setErrorMessage(Messages.getString("dropsomething.choose_folder"));
			setCantConvertStatusbarMessage(Messages.getString("dropsomething.choose_folder"));
			setCanConvert(false);
		}
		
		//log.trace(sameFolder+","+exportdir);
	}
	
	public void setMessage(String text){
		if(editor.getDropFileLabel()!=null){//before initialize
			editor.getDropFileLabel().setForeground(new Color(null,64,255,64));
			editor.getDropFileLabel().setText(text);
		}
	}
	public void setErrorMessage(String text){
		if(editor.getDropFileLabel()!=null){
			editor.getDropFileLabel().setForeground(new Color(null,255,0,0));
			editor.getDropFileLabel().setText(text);
		}
	}

	public IPreferenceStore getPreferenceStore(){
		return Akj_betasPlugin.getDefault().getPreferenceStore();
	}
	
	public boolean setFocus(){
		return tableViewer.getTable().setFocus();
	}

	public FFMpegExecuter getFFMpegExecuter() {
		return ffmpegExecuter;
	}

	public FileOverwriteControler getFileOverWriteControler() {
		if(fileOverwriteControler==null){
			fileOverwriteControler=new FileOverwriteControler(this.getViewPart().getViewSite().getShell());
		}
		return fileOverwriteControler;
	}
	
	//;
	 public abstract FFMpegPreference settingToFFMpegPreference(Setting setting);
	 
	 public boolean inconvert(Setting setting){
		boolean ret=true;
			
		ffmpegExecuter = new FFMpegExecuter();
		preference = settingToFFMpegPreference(setting);
		
		
		
		String ffmpegPath = FFMpegUI.getFFmpeg();
		
		if(ffmpegPath==null){//if no ffmpeg anyway use pure ffmpeg
			ffmpegPath=FFMpegUI.getPureFFmpeg();
		}else{
			//if pure_ffmpeg is null use ffmpeg anyway
			if(FFMpegUI.getPureFFmpeg()!=null && FFMpegUI.isUsePureFFMpeg()){
			String ac=preference.getAudioCodec();
			String vc=preference.getVideoCodec();
			
			if(ac==null){
				ac=FFMpegUtils.getDefaultAudioCodec(preference.getFormat(),preference.getExtension());
			}
			
			if(vc==null){
				vc=FFMpegUtils.getDefaultVideoCodec(preference.getFormat(),preference.getExtension());
			}
			
			if(FFMpegUtils.isAudioOnlyExtension(preference.getExtension())){
				log.info("audio only");
				 //check audio only
				if(FFMpegUI.isPureFFMpegSupportedAudioCodec(ac)){
					
						ffmpegPath=FFMpegUI.getPureFFmpeg();
						log.info("use pure_ffmpeg");
					}
				
			}else{
				if(!preference.isEnableAudio()){
					log.info("video only");
					//check video only
					if(vc!=null &&FFMpegUI.isPureFFMpegSupportedVideoCodec(vc)){
						if(FFMpegUI.getPureFFmpeg()!=null){
						ffmpegPath=FFMpegUI.getPureFFmpeg();
						log.info("use pure_ffmpeg");
						}
					}
				}else{
					log.info("audio and video");
					//check video and audio
					if(ac!=null && FFMpegUI.isPureFFMpegSupportedAudioCodec(ac) && vc!=null &&FFMpegUI.isPureFFMpegSupportedVideoCodec(vc)){
						if(FFMpegUI.getPureFFmpeg()!=null){
						ffmpegPath=FFMpegUI.getPureFFmpeg();
						log.info("use pure_ffmpeg");
						}
					}
				}
			}
		}
		}
		
		
		preference.setFfmpegPath(ffmpegPath);
		
		
		
		log.info(preference);
		//log.info(tableViewer);
		//log.info(setting);
		//log.info(tableViewer.toLabel(setting));
		//setHeaderText(tableViewer.toLabel(baseGeneric));//because setting has no name and comment
		
		DefaultFFMpegMonitor2 monitor=new DefaultFFMpegMonitor2(this,getPreferenceKey());
		
		
		monitor.setExecuteLog(getExecuteLog());
		//monitor.setAfterAction(getAfterDropSomethingAction(preference));
		
		//set after actions
		String after_action=setting.getParameters().get(GenericParametersFFMpegPreference.AFTER_ACTION);
		//log.trace("after_action:"+after_action);
		if(after_action!=null && !after_action.equals("")){
			try {
				DropsomethingAction action=(DropsomethingAction) Class.forName(after_action).newInstance();
				monitor.setAfterAction(action);
				//log.trace("action:"+action.getClass().getName());
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		ffmpegExecuter.setExecuteListener(monitor);
		
		
		//support thread when h264.
		boolean threads = FFMpegUI.isUseThread();
		if(threads){
			if(FFMpegOptions.CODEC_VIDEO_H264.equals(preference.getVideoCodec())||FFMpegOptions.CODEC_VIDEO_LIB_X264.equals(preference.getVideoCodec())){
				preference.setThreads(2);//set thread only h264 or libx264
			}
		}
		
		ffmpegExecuter.setFfmpegPreference(preference);
		
		ffmpegExecuter.setUseAvisynth(setting.getBoolean(DropFileGenericParameterSetting.USE_AVISYNTH));
		ffmpegExecuter.setIgnoreAvisynthExtensions(new String[0]);//depend on
		
		boolean sameDir=setting.getBoolean(DropFileGenericParameterSetting.SAME_DIRECTORY);
		ffmpegExecuter.setSameDirectory(sameDir);
		ffmpegExecuter.setBackup(setting.getBoolean(DropFileGenericParameterSetting.BACKUP));
		
		if(!sameDir){
			ffmpegExecuter.setExportDir((setting.getParameters().get(DropFileGenericParameterSetting.EXPORT_DIR)));
		}
		
		//execute
		ret=ffmpegExecuter.execute(setting);//TMP
		if(!ret){
			boolean r=ffmpegExecuter.deleteCurrentOutput();
			if(!r){
				log.warn("faild-but cant remove:"+ffmpegExecuter.getCurrentOutputFile().getAbsolutePath());
			}
		}else{
			//check
			if(ffmpegExecuter.getCurrentOutputFile().length()==0){
				log.warn("file-size 0:"+ffmpegExecuter.getCurrentOutputFile().getAbsolutePath());
				ret=false;
				boolean r=ffmpegExecuter.deleteCurrentOutput();
				if(!r){
					log.warn("faild-but cant remove:"+ffmpegExecuter.getCurrentOutputFile().getAbsolutePath());
				}
			}
		}
		return ret;
	}
	/*
	 * default controler.
	 */
	public class FFMpegDropSomething2SettingControler extends Composite implements SettingControler{

		public FFMpegDropSomething2SettingControler(Composite parent, int style) {
			super(parent, style);
			this.setLayout(new FillLayout());
			Composite composite=new Composite(this,SWT.NULL);
			GridLayout rootLayout=new GridLayout(1,true);
			rootLayout.marginHeight=3;
			rootLayout.marginWidth=5;
			
			composite.setLayout(rootLayout);
			
			Composite listComposite=new Composite(composite,SWT.NULL);
			GridData listData=new GridData(GridData.FILL_BOTH);
			
			listComposite.setLayoutData(listData);
			GridLayout listLayout=new GridLayout(2,false);
			listLayout.marginHeight=0;
			listLayout.marginWidth=0;
			listComposite.setLayout(listLayout);
			
			log.info("load:"+getPreferenceKey()+"."+FFMpegDropSomethingTab.SETTINGS);
			List list=GenericParametersTableViewer.loadList(getPreferenceStore().getString(getPreferenceKey()+"."+FFMpegDropSomethingTab.SETTINGS));
			
			GridData gd = new GridData(GridData.FILL_HORIZONTAL);
			//gd.minimumHeight=40;
			gd.heightHint=60;
			//gd.grabExcessVerticalSpace=true;
			tableViewer = new GenericParametersTableViewer(listComposite);
			tableViewer.getTable().setLayoutData(gd);
			tableViewer.setGenericParametersList(list);
			
			tableViewer.addSelectionChangedListener(new SelectChanged());
			
			Composite buttons=new Composite(listComposite,SWT.NULL);
			buttons.setLayout(new GridLayout(1,false));
			
			
			newSetting = new Button(buttons,SWT.NULL);
			newSetting.setText(Messages.getString("h264converter.new"));
			newSetting.addSelectionListener(new GenericNew());
			
			
			saveSetting = new Button(buttons,SWT.NULL);
			saveSetting.setText(Messages.getString("h264converter.save"));
			saveSetting.setEnabled(false);
			saveSetting.addSelectionListener(new GenericSave());
			
			//buttonList=new ArrayList();
			//settingList=new ArrayList();
			
			
			
			
			
			editor = makeGenericParameterOptionEditor(getPreferenceKey(),getPreferenceStore());//TODO change?
			
			editor.createControls(composite);
			editor.addListener(new GenericParametersEventListener(){
				public void updateModified(boolean modified) {
					saveSetting.setEnabled(modified);
				}
				
			});
			updateStatus();
			
			
			Akj_betasPlugin.getDefault().getPluginPreferences().addPropertyChangeListener( new PreferenceStoreMonitor());
			
			//select item
			int defaultSelect=getPreferenceStore().getInt(getPreferenceKey()+"."+SELECTION_INDEX);
			log.info("defaultSelect:"+defaultSelect+","+getPreferenceKey()+"."+SELECTION_INDEX);
			if(tableViewer.getTable().getItemCount()>defaultSelect){
				tableViewer.getTable().setSelection(Math.max(0,defaultSelect));//this method don't call SelectionChangedListener 
				
				}else{
					if(tableViewer.getTable().getItemCount()>0){
						tableViewer.getTable().setSelection(0);//this method don't call SelectionChangedListener 
					}else{
						log.info("item is empty");
					}
				}
			tableSelectionChanged();
			tableViewer.addSelectionChangedListener(new StoreSelect());
			
		}

		

		@Override
		public Object getControler() {
			return this;
		}
		
		

		@Override
		public Setting[] getSettings(String[] files) {
			//TODO support folder
			List<Setting> settings=new ArrayList<Setting>();
			
			DropFileGenericParameterSetting base=new DropFileGenericParameterSetting(editor.getParameters());
			
			/*
			 *maybe setted automatic
			base.set(DropFileGenericParameterSetting.USE_AVISYNTH, ""+avisynth.getSelection());
			base.set(DropFileGenericParameterSetting.SAME_DIRECTORY, ""+samefolder.getSelection());
			base.set(DropFileGenericParameterSetting.BACKUP, ""+samefolder.getSelection());
			base.set(DropFileGenericParameterSetting.EXPORT_DIR, directoryChooser.getAbsoluteFilePath());
			 */
			
			
			
			for (int i = 0; i < files.length; i++) {
				File f=new File(files[i]);
				addFiles(settings,base,f);
			}
			
			
			return settings.toArray(new Setting[settings.size()]);
		}
		
	}
	
	public boolean isSuppotedExtension(String extension){
		for (int i = 0; i < supportedFiles.length; i++) {
			if(extension.toLowerCase().equals(supportedFiles[i])){
				return true;
			}
		}
		return false;
	}
	
	private  void addFiles(List<Setting> settings,DropFileGenericParameterSetting base,File file){
		
		if(file.isDirectory()){
			String list[]=file.list();
			if(list!=null){
				for (int i = 0; i < list.length; i++) {
					File f=new File(file,list[i]);
					if(f.isDirectory()){
						addFiles(settings,base,f);
					}else{
					String ext=FileNameUtils.getExtension(list[i]);
					if(isSuppotedExtension(ext)){
						addFiles(settings,base,f);
						}
					}
				}
			}
		}else{
			DropFileGenericParameterSetting param=(DropFileGenericParameterSetting) base.clone();
			param.set(DropFileGenericParameterSetting.INPUT_VIDEO1, file.getAbsolutePath());//overwrite input
			settings.add(param);
		}
	}

	public String[] getSupportedFiles() {
		return supportedFiles;
	}

	public void setSupportedFiles(String[] supportedFiles) {
		this.supportedFiles = supportedFiles;
	}
	
	

}
